#include "bondconfigdialog.h"
#include "ui_bondconfigdialog.h"
#include <QMessageBox>
#include <QRegExpValidator>

BondConfigDialog::BondConfigDialog(const QList<ConnectionInfo>& candidates, QWidget* parent)
    : QDialog(parent), ui(new Ui::BondConfigDialog), m_selectedConns(candidates)
{
    ui->setupUi(this);
    ui->listWidgetDevices->setSelectionMode(QAbstractItemView::MultiSelection);
    setWindowTitle("配置网卡绑定");
    
    setupBondModes();
    setupDeviceList();
    
    // 设置默认值
    ui->lineEditBondName->setText("bond0");
    ui->comboBoxBondMode->setCurrentText("balance-rr (轮询)");
    ui->spinBoxMiiInterval->setValue(100);
    ui->spinBoxUpDelay->setValue(0);
    ui->spinBoxDownDelay->setValue(0);
    
    // 设置验证器
    QRegExp bondNameRegex("^bond[0-9]+$");
    ui->lineEditBondName->setValidator(new QRegExpValidator(bondNameRegex, this));
    
    // 为其他控件添加工具提示
    ui->lineEditBondName->setToolTip("绑定接口名称，如：bond0, bond1\n"
                                    "只能包含字母、数字、下划线和连字符");
    
    ui->spinBoxMiiInterval->setToolTip("MII监控间隔（毫秒）\n"
                                      "用于检测网卡链路状态\n"
                                      "推荐值：100ms");
    
    ui->spinBoxUpDelay->setToolTip("启动延迟（毫秒）\n"
                                  "网卡启动后等待多长时间才加入绑定\n"
                                  "0表示无延迟");
    
    ui->spinBoxDownDelay->setToolTip("关闭延迟（毫秒）\n"
                                    "网卡故障后等待多长时间才从绑定中移除\n"
                                    "0表示无延迟");
    
    ui->listWidgetDevices->setToolTip("选择要加入绑定的网卡\n"
                                     "至少需要选择2个网卡");
}

BondConfigDialog::BondConfigDialog(const QList<ConnectionInfo>& candidates, const QString& bondName, 
                                   const QStringList& currentMembers, QWidget* parent)
    : QDialog(parent), ui(new Ui::BondConfigDialog), m_selectedConns(candidates)
{
    ui->setupUi(this);
    ui->listWidgetDevices->setSelectionMode(QAbstractItemView::MultiSelection);
    setWindowTitle("编辑绑定成员");
    
    setupBondModes();
    setupDeviceListForEdit(currentMembers);
    
    // 设置绑定名称
    ui->lineEditBondName->setText(bondName);
    ui->lineEditBondName->setEnabled(false); // 编辑模式下不允许修改名称
    
    // 设置验证器
    QRegExp bondNameRegex("^bond[0-9]+$");
    ui->lineEditBondName->setValidator(new QRegExpValidator(bondNameRegex, this));
    
    // 为其他控件添加工具提示
    ui->lineEditBondName->setToolTip("绑定接口名称（编辑模式下不可修改）");
    
    ui->spinBoxMiiInterval->setToolTip("MII监控间隔（毫秒）\n"
                                      "用于检测网卡链路状态\n"
                                      "推荐值：100ms");
    
    ui->spinBoxUpDelay->setToolTip("启动延迟（毫秒）\n"
                                  "网卡启动后等待多长时间才加入绑定\n"
                                  "0表示无延迟");
    
    ui->spinBoxDownDelay->setToolTip("关闭延迟（毫秒）\n"
                                    "网卡故障后等待多长时间才从绑定中移除\n"
                                    "0表示无延迟");
    
    ui->listWidgetDevices->setToolTip("选择要加入绑定的网卡\n"
                                     "当前成员已自动勾选");
}

BondConfigDialog::~BondConfigDialog()
{
    delete ui;
}

void BondConfigDialog::setupBondModes()
{
    ui->comboBoxBondMode->clear();
    
    // 添加绑定模式选项，并为每个选项设置详细的工具提示
    ui->comboBoxBondMode->addItem("balance-rr (轮询)", "balance-rr");
    ui->comboBoxBondMode->setItemData(0, 
        "轮询模式：按顺序轮询发送数据包到每个网卡\n"
        "特点：\n"
        "• 提供负载均衡，所有网卡都参与传输\n"
        "• 可能产生乱序数据包\n"
        "• 需要交换机支持聚合\n"
        "适用场景：需要最大带宽且交换机支持聚合", 
        Qt::ToolTipRole);
    
    ui->comboBoxBondMode->addItem("active-backup (主备)", "active-backup");
    ui->comboBoxBondMode->setItemData(1, 
        "主备模式：只有一个网卡处于活动状态，其他作为备份\n"
        "特点：\n"
        "• 提供高可用性，故障切换快速\n"
        "• 不需要交换机特殊支持\n"
        "• 不提供负载均衡\n"
        "适用场景：追求高可用性，简单可靠（推荐新手使用）", 
        Qt::ToolTipRole);
    
    ui->comboBoxBondMode->addItem("balance-xor (XOR)", "balance-xor");
    ui->comboBoxBondMode->setItemData(2, 
        "XOR模式：基于源MAC和目标MAC地址的XOR运算选择网卡\n"
        "特点：\n"
        "• 提供负载均衡\n"
        "• 同一会话的数据包走同一网卡\n"
        "• 负载分布可能不均匀\n"
        "适用场景：需要负载均衡且希望保持会话连续性", 
        Qt::ToolTipRole);
    
    ui->comboBoxBondMode->addItem("broadcast (广播)", "broadcast");
    ui->comboBoxBondMode->setItemData(3, 
        "广播模式：所有数据包都从所有网卡发送\n"
        "特点：\n"
        "• 最大冗余性\n"
        "• 浪费带宽，增加网络负担\n"
        "• 性能较低\n"
        "适用场景：对可靠性要求极高的特殊环境", 
        Qt::ToolTipRole);
    
    ui->comboBoxBondMode->addItem("802.3ad (LACP)", "802.3ad");
    ui->comboBoxBondMode->setItemData(4, 
        "LACP模式：使用IEEE 802.3ad标准链路聚合\n"
        "特点：\n"
        "• 标准化的链路聚合协议\n"
        "• 自动协商和监控\n"
        "• 提供负载均衡和高可用性\n"
        "• 需要交换机支持LACP\n"
        "适用场景：企业环境，交换机支持LACP（推荐企业使用）", 
        Qt::ToolTipRole);
    
    ui->comboBoxBondMode->addItem("balance-tlb (发送负载均衡)", "balance-tlb");
    ui->comboBoxBondMode->setItemData(5, 
        "发送负载均衡：发送时进行负载均衡，接收时只使用一个网卡\n"
        "特点：\n"
        "• 发送方向负载均衡\n"
        "• 不需要交换机特殊支持\n"
        "• 接收方向不均衡\n"
        "适用场景：上传流量较大的场景", 
        Qt::ToolTipRole);
    
    ui->comboBoxBondMode->addItem("balance-alb (接收负载均衡)", "balance-alb");
    ui->comboBoxBondMode->setItemData(6, 
        "接收负载均衡：发送和接收都进行负载均衡\n"
        "特点：\n"
        "• 双向负载均衡\n"
        "• 不需要交换机特殊支持\n"
        "• 自动MAC地址管理\n"
        "适用场景：需要双向负载均衡且交换机不支持聚合", 
        Qt::ToolTipRole);
    
    // 设置默认选择为active-backup（推荐新手使用）
    ui->comboBoxBondMode->setCurrentIndex(1);
}

void BondConfigDialog::setupDeviceList()
{
    ui->listWidgetDevices->clear();
    for (const auto& conn : m_selectedConns) {
        QString itemText = QString("%1 (%2) - %3")
                          .arg(conn.device)
                          .arg(conn.macAddress)
                          .arg(conn.status == ConnectionStatus::Connected ? "已连接" : "未连接");
        
        QListWidgetItem* item = new QListWidgetItem(itemText);
        item->setData(Qt::UserRole, conn.device);
        item->setFlags(item->flags() | Qt::ItemIsUserCheckable);
        item->setCheckState(Qt::Checked);
        ui->listWidgetDevices->addItem(item);
    }
}

void BondConfigDialog::setupDeviceListForEdit(const QStringList& currentMembers)
{
    ui->listWidgetDevices->clear();
    for (const auto& conn : m_selectedConns) {
        QString itemText = QString("%1 (%2) - %3")
                          .arg(conn.device)
                          .arg(conn.macAddress)
                          .arg(conn.status == ConnectionStatus::Connected ? "已连接" : "未连接");
        
        QListWidgetItem* item = new QListWidgetItem(itemText);
        item->setData(Qt::UserRole, conn.device);
        item->setFlags(item->flags() | Qt::ItemIsUserCheckable);
        
        // 如果是当前成员，则勾选
        if (currentMembers.contains(conn.device)) {
            item->setCheckState(Qt::Checked);
        } else {
            item->setCheckState(Qt::Unchecked);
        }
        
        ui->listWidgetDevices->addItem(item);
    }
}

QString BondConfigDialog::getBondName() const
{
    return ui->lineEditBondName->text();
}

QString BondConfigDialog::getBondMode() const
{
    return ui->comboBoxBondMode->currentData().toString();
}

int BondConfigDialog::getMiiMonitorInterval() const
{
    return ui->spinBoxMiiInterval->value();
}

int BondConfigDialog::getUpDelay() const
{
    return ui->spinBoxUpDelay->value();
}

int BondConfigDialog::getDownDelay() const
{
    return ui->spinBoxDownDelay->value();
}

QList<QString> BondConfigDialog::getSelectedDevices() const
{
    QList<QString> devices;
    for (int i = 0; i < ui->listWidgetDevices->count(); ++i) {
        QListWidgetItem* item = ui->listWidgetDevices->item(i);
        if (item->checkState() == Qt::Checked) {
            devices << item->data(Qt::UserRole).toString();
        }
    }
    return devices;
}

bool BondConfigDialog::validateInput()
{
    if (ui->lineEditBondName->text().isEmpty()) {
        QMessageBox::warning(this, "输入错误", "请输入绑定接口名称");
        return false;
    }
    
    if (getSelectedDevices().isEmpty()) {
        QMessageBox::warning(this, "输入错误", "请至少选择一个网卡");
        return false;
    }
    
    return true;
}

void BondConfigDialog::on_buttonBox_accepted()
{
    if (!validateInput()) {
        return;
    }
    accept();
}

void BondConfigDialog::on_buttonBox_rejected()
{
    reject();
} 

void BondConfigDialog::setBondName(const QString& name) {
    ui->lineEditBondName->setText(name);
}
void BondConfigDialog::setSelectedDevices(const QList<QString>& devices) {
    for (int i = 0; i < ui->listWidgetDevices->count(); ++i) {
        QListWidgetItem* item = ui->listWidgetDevices->item(i);
        item->setSelected(devices.contains(item->text()));
    }
} 